package com.example.demo.util.filter;

import cn.hutool.bloomfilter.BitMapBloomFilter;
import com.google.common.base.Charsets;
import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnel;
import com.google.common.hash.Funnels;
import com.google.common.hash.PrimitiveSink;
import lombok.AllArgsConstructor;
import lombok.Data;

/**
 * @author: Bin.L
 * @date: 2022/6/17  15:18
 * @description: <h3>布隆过滤器 - Guava实现</h3>
 * <b> 判定不存在，100%正确  判定存在，则不一定 </b>
 * <href>https://liuyueyi.github.io/hexblog/2020/02/14/200214-Guava-BloomFilter-%E4%BD%BF%E7%94%A8%E6%89%8B%E5%86%8C/</href>
 */
public class BloomFilterExam {

    /**
     * 初始化一个存储string数据的布隆过滤器，初始化大小30, 错误率为0.1%
     */
    BloomFilter<String> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charsets.UTF_8), 30, 0.001);

    /**
     * 初始化一个hu-tool 布隆过滤器
     */
    BitMapBloomFilter filter = new BitMapBloomFilter(20);

    /**
     * 初始化一个自定义对象的布隆过滤器
     */
    BloomFilter<Student> bloomFilterStudent = BloomFilter.create(new Funnel<Student>() {
        @Override
        public void funnel(Student student, PrimitiveSink primitiveSink) {
            primitiveSink.putString(student.toString(), Charsets.UTF_8);
        }
    }, 30, 0.001);

    public static void main(String[] args) {
        BloomFilterExam bloomFilterExam = new BloomFilterExam();
        System.out.println(bloomFilterExam.ifStringHas("Hello"));
        System.out.println(bloomFilterExam.ifStringHasTool("DDD"));

        Student zs = new Student("LiSi", 36);
        System.out.println(bloomFilterExam.ifStudentHas(zs));

    }

    /**
     * 布隆过滤器（guava） 判断字符串是否存在
     *
     * @param str
     * @return
     */
    public boolean ifStringHas(String str) {
        bloomFilter.put("A");
        bloomFilter.put("B");
        bloomFilter.put("C");
        bloomFilter.put("D");
        bloomFilter.put("E");
        bloomFilter.put("F");
        bloomFilter.put("G");

        // 判断是否存在，false则表示一定不存在； true表示可能存在
        return bloomFilter.mightContain(str);

    }

    /**
     * 布隆过滤器（hu-tool） 判断字符串是否存在
     *
     * @param str
     * @return
     */
    public boolean ifStringHasTool(String str) {
        filter.add("123");
        filter.add("abc");
        filter.add("ddd");

        return filter.contains(str);
    }

    public boolean ifStudentHas(Student student){
        bloomFilterStudent.put(new Student("张三", 21));
        bloomFilterStudent.put(new Student("LiSi", 36));
        return bloomFilterStudent.mightContain(student);
    }

    @Data
    @AllArgsConstructor
    static class Student {
        private String name;
        private Integer age;

    }
}
